/**
 * dva-helper是针对dva model的类型推导支持
 */
export interface Action<TPayload = any> {
	type: string
	payload?: TPayload
	[key: string]: unknown
}

export interface EffectsCommandMap {
	put: (<TPayload>(action: Action<TPayload>) => any) | Function
	call:
	| (<Args extends Array<unknown> = Array<any>, Return = unknown>(
		fun: (...args: Args) => Return,
		...args: Args
	) => Return)
	| Function
	select: Function
	take: Function
	cancel: Function
	[key: string]: any
}

export type EffectFunction = (
	action: Action,
	effects: EffectsCommandMap,
) => Generator<any, any, any>

export type EffectType = 'takeEvery' | 'takeLatest' | 'throttle' | 'watcher'
export interface Effects {
	[effectName: string]: EffectFunction | [EffectFunction, { type: EffectType }]
}

export interface Reducers<TState> {
	[reducerName: string]: (state: TState, action: Action) => TState
}

export type Dispatch = (action: Action) => any

export interface SubscriptionsCommandMap {
	dispatch: Dispatch
	history: any
}
export interface Subscriptions {
	[subscriptionName: string]: (
		subscriptionsCommandMap: SubscriptionsCommandMap,
		done: Function,
	) => Function
}

// 基本的dva model结构
export interface Model<TState = any> {
	namespace?: string
	state?: TState
	effects?: Effects
	reducers?: Reducers<TState>
	subscriptions?: Subscriptions
	[key: string]: any
}

export function updateState<TState>(newState: TState, { payload }: Action) {
	return { ...newState, ...payload }
}

export function addTabs(newState: any, { payload }: Action) {
	const tabRoutes = newState?.tabRoutes
	const flag = tabRoutes?.filter((item: any) => item.path === payload.path)
	if (flag?.length === 1) {
		return { ...newState, tabRoutes }
	}
	const newTabRoutes = [...new Set([...tabRoutes, payload])]
	return { ...newState, tabRoutes: newTabRoutes }
}

export function deleteTabs(newState: any, { payload }: Action) {
	const tabRoutes = newState?.tabRoutes
	const newTabRoytes = tabRoutes?.filter(
		(item: any) => item.path !== payload.path,
	)
	return { ...newState, tabRoutes: newTabRoytes }
}

export function clearTabs<TState>(newState: TState) {
	return {
		...newState,
		tabRoutes: [],
	}
}
